package com.lin.missyou.service;

import com.github.wxpay.sdk.LinWXPayConfig;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import com.lin.missyou.core.LocalUser;
import com.lin.missyou.exception.http.NotFoundException;
import com.lin.missyou.exception.http.ParameterException;
import com.lin.missyou.exception.http.ServerErrorException;
import com.lin.missyou.model.Order;
import com.lin.missyou.repository.OrderRepository;
import com.lin.missyou.util.CommonUtil;
import com.lin.missyou.util.HttpRequestProxy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

@Service
@Slf4j
public class WxPaymentService {

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private LinWXPayConfig linWXPayConfig;

    @Autowired
    private OrderService orderService;

    @Value("${missyou.order.pay-callback-host}")
    private String payCallbackHost;

    @Value("${missyou.order.pay-callback-path}")
    private String payCallbackPath;

    public Map<String, String> preOrder(Long id) {

        Long uid = LocalUser.getUser().getId();

        Optional<Order> optionalOrder = orderRepository.findFirstByUserIdAndId(uid, id);

        Order order = optionalOrder
                .orElseThrow(() -> new NotFoundException(50009));
        if (order.needCancel()) {
            throw new NotFoundException(50010);
        }
        WXPay wxPay = this.assembleWxPayConfig();
        Map<String, String> params = this.makePreOrderParams(order.getFinalTotalPrice(), order.getOrderNo());
        Map<String, String> wxOrder;
        try {
            wxOrder = wxPay.unifiedOrder(params);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("调用统一下单的api失败：", e);
            throw new ServerErrorException(9999);
        }
        // 存入prepay_id 预支付交易会话标识
        if (this.unifiedOrderSuccess(wxOrder)) {
            this.orderService.updateOrderPrepayId(order.getId(), wxOrder.get("prepay_id"));
        }
        // wx.requestPayment
//        return this.makePaySignature(wxOrder);
        // 保留业务，通过模拟调用
        Map<String,String> map = new HashMap<>();
        map.put("out_trade_no", order.getOrderNo());
        return map;
    }

    // 生成签名、生成小程序调起支付API所需要的参数
    // https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_7&index=3

    private Map<String, String> makePaySignature(Map<String, String> wxOrder) {
        Map<String, String> wxPayMap = new HashMap<>();

        String packages = "prepay_id=" + wxOrder.get("prepay_id");

        wxPayMap.put("appId", linWXPayConfig.getAppID());
        wxPayMap.put("timeStamp", CommonUtil.timeStamp10());
        wxPayMap.put("nonceStr", RandomStringUtils.randomAlphabetic(32));
        wxPayMap.put("package", packages);
        wxPayMap.put("signType", "HMAC-SHA256");
        String sign;
        try {
            sign = WXPayUtil.generateSignature(wxPayMap, linWXPayConfig.getKey(), WXPayConstants.SignType.HMACSHA256);
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServerErrorException(9999);
        }

        Map<String,String> miniParams = new HashMap<>();
        miniParams.put("paySign",sign);
        miniParams.putAll(wxPayMap);
        miniParams.remove("appId");
        return miniParams;
    }


    private Boolean unifiedOrderSuccess(Map<String, String> wxOrder) {
        if (!wxOrder.get("return_code").equals("SUCCESS")
                || !wxOrder.get("result_code").equals("SUCCESS")) {
            throw new ParameterException(10007);
        }
        return true;
    }


    // 统一下单类的生成：
    public WXPay assembleWxPayConfig() {
        WXPay wxPay;
        try {
            wxPay = new WXPay(linWXPayConfig);
        } catch (Exception e) {
            log.error("生成微信支付类失败:" + e);
            throw new ServerErrorException(9999);
        }
        return wxPay;
    }

    // 组装统一下单的参数
    private Map<String, String> makePreOrderParams(BigDecimal serverFinalPrice, String orderNo) {
        String payCallbackUrl = this.payCallbackHost + this.payCallbackPath;
        Map<String, String> data = new HashMap<>();
        // 商品描述
        data.put("body", "Sleeve");
        // 商户订单号
        data.put("out_trade_no", orderNo);
        // 设备号
        data.put("device_info", "Sleeve");
        // 标价币种
        data.put("fee_type", "CNY");
        // 交易类型
        data.put("trade_type", "JSAPI");
        // 标价金额 订单总金额，单位为分
        data.put("total_fee", CommonUtil.yuanToFenPlainString(serverFinalPrice));
        // 用户标识
        data.put("openid", LocalUser.getUser().getOpenid());
        // 终端IP
        data.put("spbill_create_ip", HttpRequestProxy.getRemoteRealIp());
        // 通知地址 	https://www.weixin.qq.com/wxpay/pay.php
        data.put("notify_url", payCallbackUrl);
        return data;
    }
}
